Public Key
1. 题目
Recall that an address is the last 20 bytes of the keccak-256 hash of the address’s public key.
To complete this challenge, find the public key for the owner
‘s account.
源码
1 2 3 4 5 6 7 8 9 10 11 12
| pragma solidity ^0.4.21;
contract PublicKeyChallenge { address owner = 0x92b28647ae1f3264661f72fb2eb9625a89d88a31; bool public isComplete;
function authenticate(bytes publicKey) public { require(address(keccak256(publicKey)) == owner);
isComplete = true; } }
|
2. 分析
按题目的意思来,owner应该就是合约的部署者,我们要从交易中获取公钥,而地址的计算公式为address = address(keccak256(publicKey))
,所以只要从交易中还原出 publicKey
即可。
因为Ropsten
网络已经停用,所以要复现该题只能对合约进行修改了,将owner
修改为本地账户
1 2 3 4 5 6 7 8 9 10 11
| pragma solidity ^0.4.21;
contract PublicKeyChallenge { address owner = 0xfDc84b042c01F01C7cC6eF08452BA156844c3A5C; // 本地账户 bool public isComplete;
function authenticate(bytes publicKey) public { require(address(keccak256(publicKey)) == owner); isComplete = true; } }
|
本人自己琢磨了很久,自己写出来的一个脚本,用于通过 txhash
获取公钥。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| import { ethers } from "ethers";
const connection = ""; const provider = new ethers.providers.JsonRpcProvider(connection);
const txHash = "";
const transaction = await provider.getTransaction(txHash);
const txData = { gasLimit: transaction.gasLimit, value: transaction.value, nonce: transaction.nonce, data: transaction.data, to: transaction.to, chainId: transaction.chainId, type: transaction.type, maxFeePerGas: transaction.maxFeePerGas, maxPriorityFeePerGas: transaction.maxPriorityFeePerGas, }
const signingData = ethers.utils.serializeTransaction(txData);
const msgHash = ethers.utils.keccak256(signingData);
const signature = {r: transaction.r, s: transaction.s, v: transaction.v};
let rawPublicKey = ethers.utils.recoverPublicKey(msgHash, signature); console.log(rawPublicKey);
rawPublicKey = `0x${rawPublicKey.slice(4)}`; console.log(rawPublicKey);
|
3. 解题
部署challenge,通过脚本计算出公钥

调用hacker中的attack()
函数

解题成功~